package com.comleader.uap.core.handler;

import cn.hutool.core.util.StrUtil;
import com.comleader.uap.common.response.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.text.MessageFormat;
import java.util.StringJoiner;

import static com.comleader.uap.common.response.Result.fail;
import static com.comleader.uap.common.response.ResultEnum.*;

/**
 * 功能描述:全局异常处理类
 *
 * @Author: 连新景
 * @Date: 2024/11/23 11:21
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public Result handleException(Exception e) {
        log.error("系统异常", e);
        return fail(ERROR);

    }


    /**
     * @Description 处理请求地址不存在
     * 
     *              注意，需要设置如下两个配置项 throw-exception-if-no-handler-found: true static-path-pattern: /static/**
     * @Auhtor 连新景
     * @Date 2024/11/23 15:48
     * @param e
     * @return com.comleader.operator.common.response.Result
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    public Result handleNoHandlerFoundException(NoHandlerFoundException e) {
        log.warn("请求不存在", e);
        return fail(NOT_FOUND.getCode(), StrUtil.format("{}:{}", NOT_FOUND.getMsg(), e.getRequestURL()));

    }

    /**
     * @Description 处理请求方法不正确
     * 
     *              例如，A接口的方法为Get方式，结果请求方法为Post方式
     * @Auhtor 连新景
     * @Date 2024/11/23 15:48
     * @param e
     * @return com.comleader.operator.common.response.Result
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Result handleNoHandlerFoundException(HttpRequestMethodNotSupportedException e) {
        log.warn("请求方法不正确", e);
        return fail(METHOD_NOT_ALLOWED.getCode(), StrUtil.format("{}:{}", METHOD_NOT_ALLOWED.getMsg(), e.getMessage()));

    }

    /**
     * @param e
     * @return Result
     * @Description 参数校验异常
     * @Auhtor 连新景
     * @Date 2024/11/23 15:22
     */
    @ExceptionHandler(value = {MissingServletRequestParameterException.class, MissingServletRequestPartException.class, ConstraintViolationException.class,
        BindException.class, MethodArgumentNotValidException.class})
    public Result handleParamException(Exception e) {
        log.warn("参数校验异常", e);
        String message = "";
        // 缺失参数异常
        if (e instanceof MissingServletRequestParameterException) {
            message = MessageFormat.format("缺少参数{0}", ((MissingServletRequestParameterException)e).getParameterName());
        } else if (e instanceof MissingServletRequestPartException) {
            message = MessageFormat.format("缺少参数{0}", ((MissingServletRequestPartException)e).getRequestPartName());
        } else {
            StringJoiner sb = new StringJoiner(",");
            // 单个参数校验异常
            if (e instanceof ConstraintViolationException) {
                for (ConstraintViolation<?> constraintViolation : ((ConstraintViolationException)e).getConstraintViolations()) {
                    sb.add(constraintViolation.getMessage());
                }
            } // get请求的对象参数校验异常
            else if (e instanceof BindException) {
                for (ObjectError error : ((BindException)e).getBindingResult().getAllErrors()) {
                    sb.add(error.getDefaultMessage());
                }
                // post请求的对象参数校验异常
            } else if (e instanceof MethodArgumentNotValidException) {
                for (ObjectError error : ((MethodArgumentNotValidException)e).getBindingResult().getAllErrors()) {
                    sb.add(error.getDefaultMessage());
                }
            }
            message = sb.toString();
        }
        return fail(VALIDATE_FAILED.getCode(), message);
    }

}
